/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.binding.mapping;

import org.jdesktop.beansbinding.*;

/**
 * Class holding infomations for a {@link Binding}.
 * 
 * @author M. Hautle
 */
@SuppressWarnings("unchecked")
public class BindingInfos {
    /** Represents an undefined value. */
    protected static final Object UNDEFINED = new Object();

    /** The path to the property */
    private final String path;

    /** The converter to use or null */
    private Converter converter;

    /** The source null value to use or null */
    private Object sourceNullValue;

    /** The source unreadable value to use, {@link #UNDEFINED} or null */
    private Object sourceUnreadableValue = UNDEFINED;

    /** The target null value to use or null */
    private Object targetNullValue;

    /** The validator to use or null */
    private Validator validator;

    /** A sub/related binding or null. */
    private ISubBinding subBinding;

    /**
     * Default constructor
     * 
     * @param path The path to the property
     */
    public BindingInfos(final String path) {
        this.path = path;
    }

    /**
     * Default constructor
     * 
     * @param property The name of the property
     * @param converter The converter to use
     * @param sourceNullValue The source null value
     * @param sourceUnreadableValue The source unreadable value
     * @param targetNullValue The target null value
     * @param validator The validator
     */
    public BindingInfos(final String property, final Converter converter, final Object sourceNullValue, final Object sourceUnreadableValue,
            final Object targetNullValue, final Validator validator) {
        this.path = property;
        this.converter = converter;
        this.sourceNullValue = sourceNullValue;
        this.sourceUnreadableValue = sourceUnreadableValue;
        this.targetNullValue = targetNullValue;
        this.validator = validator;
    }

    /**
     * Returns the converter for this binding.
     * 
     * @return the converter
     */
    public Converter getConverter() {
        return converter;
    }

    /**
     * Sets the converter for this binding.
     * 
     * @param converter the converter to set, may be <code>null</code>
     */
    public void setConverter(final Converter converter) {
        this.converter = converter;
    }

    /**
     * Sets the value representing <code>null</code> in the source.
     * 
     * @return the sourceNullValue
     */
    public Object getSourceNullValue() {
        return sourceNullValue;
    }

    /**
     * Returns the value representing <code>null</code> in the source.
     * 
     * @param sourceNullValue the sourceNullValue to set, may be <code>null</code>
     */
    public void setSourceNullValue(final Object sourceNullValue) {
        this.sourceNullValue = sourceNullValue;
    }

    /**
     * Clears the value of {@link #sourceUnreadableValue} to undefined.
     */
    public void unsetSourceUnreadableValue() {
        sourceUnreadableValue = UNDEFINED;
    }

    /**
     * Returns the value representing an unreadable source.
     * 
     * @return the sourceUnreadableValue
     */
    public Object getSourceUnreadableValue() {
        return sourceUnreadableValue;
    }

    /**
     * Sets the value representing an unreadable source.
     * 
     * @param sourceUnreadableValue the sourceUnreadableValue to set, may be <code>null</code>
     */
    public void setSourceUnreadableValue(final Object sourceUnreadableValue) {
        this.sourceUnreadableValue = sourceUnreadableValue;
    }

    /**
     * Returns the value representing <code>null</code> in the target.
     * 
     * @return the targetNullValue
     */
    public Object getTargetNullValue() {
        return targetNullValue;
    }

    /**
     * Sets the value representing <code>null</code> in the target.
     * 
     * @param targetNullValue the targetNullValue to set, may be <code>null</code>
     */
    public void setTargetNullValue(final Object targetNullValue) {
        this.targetNullValue = targetNullValue;
    }

    /**
     * Sets the validator of this binding.
     * 
     * @return the validator
     */
    public Validator getValidator() {
        return validator;
    }

    /**
     * Returns the validator of this binding.
     * 
     * @param validator the validator to set, may be <code>null</code>
     */
    public void setValidator(final Validator validator) {
        this.validator = validator;
    }

    /**
     * Returns the sub binding.
     * 
     * @return the subbinding or null
     */
    public ISubBinding getSubBinding() {
        return subBinding;
    }

    /**
     * Sets the subbinding.
     * 
     * @param subBinding The subBinding to set, may be <code>null</code>
     */
    public void setSubBinding(ISubBinding subBinding) {
        this.subBinding = subBinding;
    }

    /**
     * Returns the path to the source property of this binding.
     * 
     * @return the path
     */
    public String getPath() {
        return path;
    }

    /**
     * Configures the binding according to the values in this Info Bean.<br>
     * If a value in this Bean is null, then the property in the binding won't be touched.
     * 
     * @param binding The binding to configure
     */
    void configure(final Binding binding) {
        binding.setConverter(converter);
        binding.setSourceNullValue(sourceNullValue);
        binding.setTargetNullValue(targetNullValue);
        binding.setValidator(validator);
        if (sourceUnreadableValue == UNDEFINED)
            binding.unsetSourceUnreadableValue();
        else
            binding.setSourceUnreadableValue(sourceUnreadableValue);
    }

    /**
     * Bind the subBinding if one exists.
     */
    void bindSubBinding() {
        if (subBinding != null)
            subBinding.bind(this);
    }

    /**
     * Unbind the subBinding if one exists.
     */
    void unbindSubBinding() {
        if (subBinding != null)
            subBinding.unbind(this);
    }
}
